using System.IO;
using System.Web;
using FluentNHibernate.Automapping;
using FluentNHibernate.Conventions;
using FluentNHibernate.Conventions.Instances;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using Lucene.Net.Analysis;
using NHibernate.Search.Event;
using NHibernate.Search.Store;
using NHibernate.Tool.hbm2ddl;
using Ninject.Modules;
using Wikey.Domain.Mappings;
using Wikey.Entity;
using Wikey.Domain.Repository;
using Wikey.Domain.Validation;
using Wikey.Extensibility.Interfaces;

namespace Wikey.Domain.Components
{
    public class CoreDependencies : Module {
        public override void Load() {

            var database = MsSqlConfiguration.MsSql2005
                .ConnectionString(
                c => c.Server(@".\SQL2008")
                         .Database("Wikey")
                         .Username("wikey")
                         .Password("wikey"));

            AutoMap.AssemblyOf<Page>()
                //.Where(type => type.Namespace == "Wikey.Entity")
                .UseOverridesFromAssemblyOf<PageOverride>();

            var configuration = Fluently.Configure()
                .Database(database)
                .Mappings(
                m =>
                m.FluentMappings
                    .AddFromAssemblyOf<UserMap>()
                    .Conventions.AddFromAssemblyOf<TableNameConvention>()
                    .ExportTo(ExportPath())
                )
                // .ExposeConfiguration( SetSearchConfiguration )
                .ExposeConfiguration(BuildSchema);

            
            Bind<ISessionSource>()
                .To<SessionSource>()
                .InRequestScope()
                .WithConstructorArgument("config", configuration);

            
            Bind<IValidator>().To<Validator>();
            Bind<IEncryptor>().To<Encryptor>();

            Bind<IContentNodeRepository>().To<ContentNodeRepository>().InRequestScope();
            Bind<IUserRepository>().To<UserRepository>().InRequestScope();
            Bind<IDocumentRepository>().To<DocumentRepository>().InRequestScope();
            Bind<IPageRepository>().To<PageRepository>().InRequestScope();
            Bind<ICommentRepository>().To<CommentRepository>().InRequestScope();
            Bind<ITagRepository>().To<TagRepository>().InRequestScope();
            Bind<IMacroRepository>().To<MacroRepository>().InRequestScope();
            Bind<ISpaceRepository>().To<SpaceRepository>().InRequestScope();
            Bind<ITemplateRepository>().To<TemplateRepository>().InRequestScope();
            Bind<IRoleRepository>().To<RoleRepository>().InRequestScope();
            Bind<ILogger>().To<Logger>().InSingletonScope();
            Bind<IDynamicDataSource>().To<DynamicDataSource>().InSingletonScope();
        }

        private static void SetSearchConfiguration(NHibernate.Cfg.Configuration cfg)
        {
            cfg.SetProperty("hibernate.search.default.directory_provider",
                            typeof (RAMDirectoryProvider).AssemblyQualifiedName);
            cfg.SetProperty(NHibernate.Search.Environment.AnalyzerClass,
                            typeof (StopAnalyzer).AssemblyQualifiedName);

            cfg.SetListener(NHibernate.Event.ListenerType.PostUpdate, new FullTextIndexEventListener());
            cfg.SetListener(NHibernate.Event.ListenerType.PostInsert, new FullTextIndexEventListener());
            cfg.SetListener(NHibernate.Event.ListenerType.PostDelete, new FullTextIndexEventListener());
        }

        private static void BuildSchema(NHibernate.Cfg.Configuration cfg)
        {
            try
            {
                var schemaExporter = new SchemaExport(cfg);
                schemaExporter.SetOutputFile(Path.Combine(
                    HttpContext.Current.Server.MapPath("~/")
                    , "schema.sql"));
                schemaExporter.Create(true, false);

            }
            catch
            {
                
            }
        }


        private const string DbFile = "~/NHibernate/";

        private string ExportPath()
        {
            if (HttpContext.Current == null)
            {
                return string.Empty;
            }
            var absolutePath = HttpContext.Current.Server.MapPath(DbFile);
 
           if( !Directory.Exists( absolutePath ) )
           {
               Directory.CreateDirectory(absolutePath);
           }

            return absolutePath;
        }
    }

    public class TableNameConvention : IClassConvention
    {
        public void Apply(IClassInstance instance)
        {
            instance.Table(instance.EntityType.Name + "s");         
        }

    }
}